/*
 * $Id: ShemJobTask.java,v 1.7 2009/10/07 19:15:18 afaichun Exp $
 * 
 * Copyright (C) 2008 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.processor.dispatcher.tasks;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.database.dao.IFileTransferDetailsDAO;
import com.ge.healthcare.autosc.common.database.dao.IRequestDAO;
import com.ge.healthcare.autosc.common.database.dao.IRequestPropertiesDAO;
import com.ge.healthcare.autosc.common.database.pojo.ActFileTransferDetails;
import com.ge.healthcare.autosc.common.database.pojo.ActRequest;
import com.ge.healthcare.autosc.common.database.pojo.ActRequestProperties;
import com.ge.healthcare.autosc.common.database.pojo.ActTask;
import com.ge.healthcare.autosc.common.dbLogger.StepLogger;
import com.ge.healthcare.autosc.common.exceptions.BasicException;
import com.ge.healthcare.autosc.common.util.ApplicationInfo;
import com.ge.healthcare.autosc.common.util.PropertyConstants;
import com.ge.healthcare.autosc.processor.PrcCodeConstants;
import com.ge.healthcare.autosc.processor.exception.GuidanceLoaderException;
import com.ge.healthcare.autosc.processor.exception.MagnetMonitorProcessorException;
import com.ge.healthcare.autosc.processor.exception.ShemJobException;
import com.ge.healthcare.autosc.processor.magmon.IMagnetMonitorProcessor;
import com.ge.healthcare.autosc.processor.magmon.MagnetMonitorProcessor;
import com.ge.healthcare.autosc.processor.shemjob.ShemRequestData;
import com.ge.healthcare.autosc.processor.shemjob.guidance.dataset.RequestDataSet;
import com.ge.healthcare.autosc.processor.shemjob.guidance.loader.ShemJobGuidanceLoader;
import com.ge.healthcare.autosc.processor.shemjob.reader.ShemReaderFactory;
import com.ge.healthcare.autosc.processor.shemjob.reader.ShemTextReader;
/**
 * Abstract class for all Shem task
 * @author 212042946
 *
 */
public abstract class ShemJobTask extends BasicTask {

	protected static IFileTransferDetailsDAO ftDetailsDAO = null;
	protected static IRequestPropertiesDAO requestPropertiesDAO = null; 
	protected static IRequestDAO requestDAO = null;
	
	protected ShemRequestData requestData = null;
	protected ActTask task = null;
	protected ActRequest request = null;
	
	private ShemJobGuidanceLoader shemJobGuidanceLoader = null;
	private IMagnetMonitorProcessor magMonProcessor = null;
	HashMap<String, String> requestProperties = new HashMap<String, String>(); 
		
	/**
	 * Spring init method.
	 */
	public void init() {
		Assert.notNull(ftDetailsDAO,
				"ActFileTransferDetailsDAO object is required. Use setActFileTransferDetailsDAO() to provide one.");
		Assert.notNull(requestPropertiesDAO,
				"ActRequestPropertiesDAO object is required. Use setActRequestPropertiesDAO() to provide one.");
		Assert.notNull(requestDAO,
				"ActRequestDAO object is required. Use setActRequestDAO() to provide one.");
	}
	
	@Override
	public void executeTask(ActTask actTask) {
		task = actTask;
		try {
			cleanUpShemFile();
			initializeInstance();
			createFileDataSet();
			setupMagnetMonitorProcessor();
			processRequestDataSet();
			processEvent();
		} catch (BasicException be) {
			ASCLogger.error(this.getClass(), "executeTask", be, true);
			throw new ShemJobException(be, be.getErrorCode());
		} finally {
			cleanUp();
		}
	}

	/**
	 * Set ActFileTransferDetailsDAO
	 * @param fileTransferDetailsDAO
	 */
	public void setActFileTransferDetailsDAO(IFileTransferDetailsDAO fileTransferDetailsDAO) {
		ftDetailsDAO = fileTransferDetailsDAO;
	}
	
	/**
	 * Set ActRequestPropertiesDAO
	 * @param requestPropertiesDAO
	 */
	public void setActRequestPropertiesDAO(IRequestPropertiesDAO requestPropertiesDAO) {
		ShemJobTask.requestPropertiesDAO = requestPropertiesDAO;
	}
	
	/**
	 * Set ActRequestDAO
	 * @param requestDAO
	 */
	public void setActRequestDAO(IRequestDAO requestDAO) {
		ShemJobTask.requestDAO = requestDAO;
	}

	/**
	 * Perform cleanup after task is processed.
	 */
	protected void cleanUp() {
		if(magMonProcessor != null) {
			magMonProcessor.cleanUp();
		}
	}
	
	/**
	 * Get service Id. Subclass must provide this.
	 * @return service Id
	 */
	protected abstract String getServiceId();
	
	/**
	 * Get createdBy. Subclass must provide this. 
	 * @return
	 */
	protected abstract String getCreatedBy();
	
	/**
	 * Initialize the task. This includes:
	 * <ol>
	 * <li>Load ShemJob guidance</li>
	 * <li>Initialize MagnetMonitorProcessor</li>
	 * <li>Load request properties</li>
	 * </ol>
	 * @throws GuidanceLoaderException
	 */
	private void initializeInstance() throws GuidanceLoaderException {
		shemJobGuidanceLoader = new ShemJobGuidanceLoader();
		shemJobGuidanceLoader.load();
		magMonProcessor = new MagnetMonitorProcessor();
		request = requestDAO.getByRequestID(task.getRequestId());
		if(request != null) {
			magMonProcessor.selectSite(request.getSystemId());
			StepLogger.addStepLog("Selected site: " + request.getSystemId());
			Map<String, String> props = requestPropertiesDAO.getRequestPropertiesByRequestId(request.getRequestId());
			if(props != null) {
				requestProperties.putAll(props);
			}
			StepLogger.addStepLog("Handling Shemjob function: " + requestProperties.get(ActRequestProperties.CREATED_BY));
		} else {
			throw new ShemJobException("Failed to find request for task " + task, PrcCodeConstants.PRC_F_SHM_002);
		}
	}

	/**
	 * Create Shem request data that will be processed.
	 * @throws BasicException Failed to load request data
	 */
	private void createFileDataSet() throws BasicException {
		try {
			List<ActFileTransferDetails>ftDetails = 
					ftDetailsDAO.getExternalFileTransferLstByRequestId(task.getRequestId());
			String tdfFileName = requestProperties.get(ActRequestProperties.TDF_FILE);
			StepLogger.addStepLog("tdfname=" + tdfFileName);
			requestData = new ShemRequestData(ftDetails, tdfFileName);
		} catch (BasicException be) {
			throw new BasicException(be, PrcCodeConstants.PRC_F_SHM_003);
		}
	}
	
	/*
	 * Setup MagnetMonitorProcessor
	 */
	private void setupMagnetMonitorProcessor() {
		if(request != null) {
			try {
				magMonProcessor.selectSite(request.getSystemId());
				String minorFunction = getCreatedBy();
				magMonProcessor.selectEvent(getServiceId(), minorFunction);
				magMonProcessor.verifyRegistered();
				ASCLogger.info(this.getClass(), "setupMagnetMonitorProcess", "Processing majorFunction " + getServiceId() + ", minorFunction " + minorFunction); 
				StepLogger.addStepLog("Selected event for : " + getServiceId() + "," + minorFunction);
			} catch (MagnetMonitorProcessorException mmpe) {
				throw new ShemJobException(mmpe, PrcCodeConstants.getCode(mmpe, PrcCodeConstants.PRC_F_SHM_004));
			}
		}
	}
	
	/*
	 * Process Request data set
	 */
	private void processRequestDataSet() throws BasicException {
		int passNumber = new Integer(
				ApplicationInfo.getInstance().getProperty(PropertyConstants.SHEMJOB_PROCESS_DATA_PASS, "2"))
				.intValue();
		for(int currentPass = 1; currentPass <= passNumber; currentPass++) {
			processRequestDataSet(currentPass);
		}
	}
	
	/*
	 * Process request data set
	 */
	private void processRequestDataSet(int currentPass) 
		throws BasicException {
		try {
			ArrayList<String> dataFileNames = requestData.getDataSetList();
			for(int idx=0;idx < dataFileNames.size();idx++) {
				String dataSetId = dataFileNames.get(idx);
				RequestDataSet guidanceDataSet = shemJobGuidanceLoader.getRequestDataSet(dataSetId);
				if(guidanceDataSet.isCurrentPass(currentPass)) {
					ShemTextReader reader = ShemReaderFactory.getDataSetReader(guidanceDataSet.getReadingClassName());
					com.ge.healthcare.autosc.common.requestData.RequestDataSet requestDataSet = requestData.getDataSet(dataSetId);
					magMonProcessor.processDataSet(task, dataSetId, reader, requestDataSet);
				}
			}
		} catch (BasicException be) {
			throw new BasicException(be, PrcCodeConstants.getCode(be, PrcCodeConstants.PRC_F_SHM_005));
		}
	}
	
	private void processEvent() throws BasicException {
		try {
			magMonProcessor.processCurrentEvent();
		} catch (BasicException be) {
			throw new BasicException(be, PrcCodeConstants.getCode(be, PrcCodeConstants.PRC_F_SHM_006));
		}
	}
	
	/**
	 * Clean up file that is in direction of 'SHEM'. Files are cleaned up
	 * here only when this task was previously failed after some shem files
	 * had been processed.
	 */
	private void cleanUpShemFile() {
		ftDetailsDAO.deleteByRequestIdAndDirection(task.getRequestId(), IFileTransferDetailsDAO.SHEM_FROM_DEVICE);
	}
}
